package com.shuiyun.chat.handler;

import com.shuiyun.chat.entity.bo.DeserializationBO;
import com.shuiyun.chat.entity.message.Message;
import com.shuiyun.chat.enums.MessageType;
import com.shuiyun.chat.utils.DeserializationUtil;
import com.shuiyun.chat.utils.SerializeUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author shuiyun
 * @program oicq
 * @description 消息编解码处理器
 * @create 2021-05-12 11:38
 **/
@Slf4j
@ChannelHandler.Sharable
@Component
public class MessageCodecHandler extends MessageToMessageCodec<ByteBuf, Message> {

    /**
     * 加密消息
     * @param message 消息
     * @author shuiyun
     * @date 2021/5/12 13:53
     */
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Message message, List<Object> list) throws Exception {
        // 序列化方式 TODO 暂时写死 后续可以进行配置
        int serializeType = 1;
        SerializeUtils serializeUtils = new SerializeUtils();

        ByteBuf buffer = channelHandlerContext.alloc().buffer();
        // 1. 4个字节的魔法字 -> 4 TODO 魔法字可以进行配置 用于校验消息是否合法
        buffer.writeInt(1234);
        // 2. 版本 -> 1
        buffer.writeByte(1);
        // 3. 字节序列化方式 0-jdk 1-json -> 1
        buffer.writeByte(serializeType);
        // 4. 消息类型 -> 4
        buffer.writeInt(message.getMessageType());
        // 头信息设置完毕 一共是 10个字节

        // 5. 序列化实体并且写入长度和内容
        byte[] bytes = serializeUtils.invoke(serializeType, message);
        buffer.writeInt(bytes.length);
        buffer.writeBytes(bytes);
        list.add(buffer);
    }

    /**
     * 消息解密
     * @param byteBuf 字节码
     * @author shuiyun
     * @date 2021/5/12 13:54
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        // 魔法字
        int magicNum = byteBuf.readInt();
        // 版本
        byte version = byteBuf.readByte();
        // 系列化方式
        byte serializeType = byteBuf.readByte();
        // 消息类型
        int messageType = byteBuf.readInt();
        // 正文长度
        int length = byteBuf.readInt();
        // 读取内容
        byte[] message = new byte[length];
        byteBuf.readBytes(message,0,length);
        int type = Byte.toUnsignedInt(serializeType);
        DeserializationUtil deserializationUtil = new DeserializationUtil();
        Message result = deserializationUtil.invoke(type, DeserializationBO.builder().bytes(message).message(MessageType.getMessage(messageType)).build());
        list.add(result);
    }
}
